利用梅尔倒谱系数(MFCC)及空间聚类算法实现音色识别

写在前面

2016年4月参加了哈尔滨工业大学深圳研究生院举办的创新创业比赛,司职算法组长,切入点定在了音色识别和相似明星音才艺展示推荐算法上,不才,拿到了一等奖,趁佳节未散与大家分享。

项目进度安排

2016年1月~2016年3月:前期工作中了解学习了语音信号处理的基本原理,查阅有关文献了解到了声音音色信息的描述方式,梅尔(Mel)倒谱系数的意义,推导了相关公式并实现了MFCC(Mel Frequency Cepstral Coefficient)参数的计算,阅读并了解了有关说话人识别,音色识别和MFCC参数的相关应用情况。

2016年4月~2016年6月:后期工作中组内部分成员同软件组(还是什么组?)共同合作完成了由算法向实际应用的转化,另一部分成员进行了后续的算法优化,添加了噪声预处理环节,并期待利用支持向量机(SVM),K-均值聚类(K-means)等机器学习算法实现更好的音色识别效果。

项目实施方案与原理

在MFCC参数提取方面,我们遵循[1]中所述的计算流程,编程实现了对一段语音的MFCC参数提取:

具体的编程环节这里暂时不介绍,从Mel刻度转换后我们得到的MFCC参数多达40余个,为了避免特征泛化导致识别率降低,我们需要对这些特征进行筛选。还好这个工作已经有人替我们完成[2],通过离散傅里叶变换(DCT),我们可以得到需要的C2~C16的特征值作为说话人的音色描述子。用了别人的工作,我们还应该本着严谨的态度对其进行验证。这里我们设计一个二类分类实验,利用SVM来进行音色描述子优劣的描述。利用现有数据库的测试数据,我们实现了如下的测试结果:


SVM十次十折实验利用MFCC参数作为特征可实现97.5%的识别准确率。

SVM再处理多类分类问题时存在着运算速度和效率上的限制,从这一点考虑,我们先使用了最简单的最小欧式距离法进行识别,该算法在小参考集下运算速度较快,但大参考集时运算耗时会严重增长,为了解决这个问题,我们提出了使用K-means聚类+最小欧式距离结合的方法,利用聚类算法,将大型的数据集分成若干个小的数据集,并且以聚类中心作为该集合的label,识别过程中首先进行类间匹配,接下来再进行类内匹配。

算法上的项目创新点有二:

其一,首次使用MFCC参数作为歌手的识别推荐系统下,需要解决很多噪声处理和歌手特征提取的难题;

其二,在识别过程中采用了无监督学习和有监督学习结合的方法,加快识别速度。

不足之处的反思

目前采用的特征还只是MFCC参数这一个角度,特征的类型较为单一,在未来的研究中,可以增加一些更为有效的特征作为音色的描述,同时,可以引进更大的标准数据库,在互联网上利用爬虫等数据挖掘手段收集更多的明星声音来扩充我们的标准库。作为一款娱乐应用,这个APP已经具备了初步市场化的能力,但是一首歌终究还是由音色,音调和节奏等多方面组成,我们推荐结果的好坏是一个取决于APP使用者很主观的评价准则。如何实现APP的可持续发展,如何让APP保持活力,维持用户数量和用户活跃度等等都是很不确定的因素。


reference:

[1]http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/#deltas-and-delta-deltas

[2]甄斌,吴玺宏,刘志敏,迟惠生. 语音识别和说话人识别中各倒谱分量的相对重要性[J].北京大学学报(自然科学版),2001,03:371-378.


Attachment:

展示一下最后APP的结果:


以及移动端的逻辑关系:






  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是在Matlab中提取翻转梅尔频率倒系数MFCC)的示例代码: ```matlab % 读取音频文件 [y, Fs] = audioread('example.wav'); % 预处理:对信号进行预加重,使用高通滤波器 preemph = [1, -0.97]; y = filter(preemph, 1, y); % 帧分割:将信号分为若干个帧 frame_size = 0.025; % 帧长(单位:秒) frame_shift = 0.01; % 帧移(单位:秒) frame_length = frame_size * Fs; % 帧长(单位:采样点) frame_step = frame_shift * Fs; % 帧移(单位:采样点) num_frames = floor((length(y) - frame_length) / frame_step) + 1; frames = zeros(frame_length, num_frames); for i = 1:num_frames start_idx = (i-1) * frame_step + 1; frames(:, i) = y(start_idx : start_idx + frame_length - 1); end % 加窗:对每个帧进行汉明窗加窗 window = hamming(frame_length); frames = bsxfun(@times, frames, window); % 快速傅里叶变换:对每个帧进行FFT计算 NFFT = 512; fft_frames = fft(frames, NFFT, 1); % 能量:计算每个帧的能量 power_frames = abs(fft_frames).^2 / NFFT; % 梅尔滤波器组:计算梅尔滤波器组的系数 num_filters = 20; mel_low_freq = 0; % 梅尔滤波器组的最低频率 mel_high_freq = 2595 * log10(1 + (Fs/2) / 700); % 梅尔滤波器组的最高频率 mel_points = linspace(mel_low_freq, mel_high_freq, num_filters + 2); hz_points = 700 * (10.^(mel_points / 2595) - 1); bin = floor((NFFT + 1) * hz_points / Fs); fbank = zeros(num_filters, NFFT / 2 + 1); for m = 1:num_filters f_m_minus = bin(m); f_m = bin(m+1); f_m_plus = bin(m+2); for k = f_m_minus:f_m fbank(m, k+1) = (k - bin(m)) / (bin(m+1) - bin(m)); end for k = f_m:f_m_plus fbank(m, k+1) = (bin(m+2) - k) / (bin(m+2) - bin(m+1)); end end % 翻转梅尔频率倒系数:计算每个帧的MFCC num_ceps = 12; mfcc = zeros(num_ceps, num_frames); for i = 1:num_frames % 将能量乘以梅尔滤波器组的系数,得到每个滤波器的输出能量 filter_energies = fbank * power_frames(:, i); % 取对数,得到滤波器组的对数输出能量 log_filter_energies = log(filter_energies + eps); % 对上面的对数输出能量进行离散余弦变换(DCT) mfcc(:, i) = dct(log_filter_energies); % 取前 num_ceps 个系数作为MFCC mfcc(:, i) = mfcc(1:num_ceps, i); end % 翻转MFCC:对每个MFCC向量进行翻转 rfcc = flipud(mfcc); ``` 以上代码中,翻转MFCC的操作是通过 `flipud` 函数实现的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值